package com.ccl.iot;import java.util.ArrayList;

import com.ccl.iot.privates.ListMap;
import com.ccl.iot.object.IOTInfoWithValue;

public class IOTInfoLogger {
	private ListMap<String, String> iAdds = null;
	private ListMap<String, String> iChanges = null;
	private ListMap<String, String> iRemoves = null;
	
	public synchronized boolean add(String aName, String aValue){
		if (aName != null){
			if (iRemoves != null){
				synchronized(iRemoves){
					String tValue = iRemoves.getValue(aName);
					
					if (tValue != null){
						if (iRemoves.remove(aName)){
							if (tValue.equals(aValue)){
								return true;
							}else{
								return change(aName, aValue);
							}
						}
					}
				}
			}
			
			if (iAdds == null){
				iAdds = new ListMap<String, String>();
			}
			//Debugger.Error("Add " + aName + " = " + aValue);
			return iAdds.put(aName, aValue);
		}
		
		return false;
	}
	
	public boolean add(IOTInfoWithValue aInfo){
		if (aInfo != null){
			return add(aInfo.getName(), aInfo.getValue());
		}
		
		return false;
	}
	
	public boolean add(ArrayList<IOTInfoWithValue> aInfos){
		if (aInfos != null){
			boolean tResult = true;
			
			for (int i = 0, tCount = aInfos.size(); i < tCount; i++){
				tResult &= add(aInfos.get(i));
			}
			
			return tResult;
		}
		
		return false;
	}
	
	public synchronized boolean change(String aName, String aValue){
		if (aName != null){
			if (iAdds != null){
				if (iAdds.containsKey(aName)){
					return iAdds.put(aName, aValue);
				}
			}
			
			if (iChanges == null){
				iChanges = new ListMap<String, String>();
			}
			//Debugger.Error("Change " + aName + " = " + aValue);
			return iChanges.put(aName, aValue);
		}
		
		return false;
	}
	
	public boolean change(IOTInfoWithValue aInfo){
		if (aInfo != null){
			return change(aInfo.getName(), aInfo.getValue());
		}
		
		return false;
	}
	
	public boolean change(ArrayList<IOTInfoWithValue> aInfos){
		if (aInfos != null){
			boolean tResult = true;
			
			for (int i = 0, tCount = aInfos.size(); i < tCount; i++){
				tResult &= change(aInfos.get(i));
			}
			
			return tResult;
		}
		
		return false;
	}
	
	public synchronized boolean remove(String aName, String aValue){
		if (aName != null){
			if (iAdds != null){
				synchronized(iAdds){
					if (iAdds.remove(aName)){
						return true;
					}
				}
			}
			if (iChanges != null){
				synchronized(iChanges){
					iChanges.remove(aName);
				}
			}
			
			if (iRemoves == null){
				iRemoves = new ListMap<String, String>();
			}else{
				synchronized(iRemoves){
					if (iRemoves.containsKey(aName)){
						return true;
					}
				}
			}
			
			//Debugger.Error("Remove " + aName);
			return iRemoves.add(aName, aValue);
		}
		
		return false;
	}
	
	public boolean remove(IOTInfoWithValue aInfo){
		if (aInfo != null){
			return remove(aInfo.getName(), aInfo.getValue());
		}
		
		return false;
	}
	
	public boolean remove(ArrayList<IOTInfoWithValue> aInfos){
		if (aInfos != null){
			boolean tResult = true;
			
			for (int i = 0, tCount = aInfos.size(); i < tCount; i++){
				tResult &= remove(aInfos.get(i));
			}
			
			return tResult;
		}
		
		return false;
	}
	
	public boolean change(ArrayList<IOTInfoWithValue> aOldInfos, ArrayList<IOTInfoWithValue> aNewInfos){
		if (aOldInfos != null && aNewInfos != null){
			boolean tResult = true;
			int i, j, tCount1, tCount2, tCompared;
			IOTInfoWithValue tOld, tNew;
			ArrayList<IOTInfoWithValue> tNews = new ArrayList<IOTInfoWithValue>(aNewInfos);
			ArrayList<IOTInfoWithValue> tChanges = null;
			ArrayList<IOTInfoWithValue> tRemoves = null;
			
			for (i = 0, tCount1 = aOldInfos.size(); i < tCount1; i++){
				if ((tOld = aOldInfos.get(i)) != null){
					for (j = 0, tCount2 = tNews.size(); j < tCount2; j++){
						if ((tNew = tNews.get(j)) != null){
							tCompared = tOld.compareIgnoreID(tNew);
							
							if (tCompared == 0){	//Old valid
								tNews.remove(tNew);
								
								break;
							}else if (tCompared == 2){	//Value changed
								if (tChanges == null){
									tChanges = new ArrayList<IOTInfoWithValue>();
								}
								
								tChanges.add(tNew);
								tNews.remove(tNew);
								
								break;
							}
						}
					}
					
					if (j == tCount1){
						if (tRemoves == null){
							tRemoves = new ArrayList<IOTInfoWithValue>();
						}
						
						tRemoves.add(tOld);
					}
				}
			}
			
			if (tNews.size() > 0){
				tResult = add(tNews);
			}
			
			if (tChanges != null){
				tResult &= change(tChanges);
			}
			
			if (tRemoves != null){
				tResult &= remove(tRemoves);
			}
			
			return tResult;
		}
		
		return false;
	}
	
	public synchronized boolean isChanged(){
		return (iAdds != null && iAdds.size() > 0) || (iRemoves != null && iRemoves.size() > 0) || (iChanges != null && iChanges.size() > 0);
	}
	
	public synchronized ListMap<String, String> getAdded(){
		return iAdds;
	}
	
	public synchronized ListMap<String, String> getChanged(){
		return iChanges;
	}
	
	public synchronized ListMap<String, String> getRemoved(){
		return iRemoves;
	}
	
	public synchronized boolean removeLog(String aName){
		if (iAdds != null ){
			synchronized(iAdds){
				if (iAdds.remove(aName)){
					return true;
				}
			}
		}
		
		if (iChanges != null ){
			synchronized(iChanges){
				if (iChanges.remove(aName)){
					return true;
				}
			}
		}
		
		if (iRemoves != null){
			synchronized(iRemoves){
				if (iRemoves.remove(aName)){
					return true;
				}
			}
		}
		
		return false;
	}
	
	public void cleanLog(){
		if (iAdds != null ){
			synchronized(iAdds){
				if (iAdds.size() > 0){
					iAdds.clear();
				}
			}
		}
		
		if (iChanges != null ){
			synchronized(iChanges){
				if (iChanges.size() > 0){
					iChanges.clear();
				}
			}
		}
		
		if (iRemoves != null){
			synchronized(iRemoves){
				if (iRemoves.size() > 0){
					iRemoves.clear();
				}
			}
		}
	}
}
